for(let i =0;i<10;i++){
    let i=9;
    console.log(i);
}

let b={n:1};
let a=b;
a.x=a={n:2}  
//JavaScript 总是严格按照从左至右的顺序来计算表达式。a.x会在{n:1}地址声明一个x等待赋值 (为什么这个地址会一直存在，因为有b在引用着) 所以最后被赋值的是{n:1} 这个地址
console.log(a) //{n: 2}
console.log(b) //{n: 1,x:{n:2}}

// let b={n:1};
// let a=b;
// a=a.x={n:2}  //换一下a和a.x 也是一样的结果
// console.log(a) //{n: 2}
// console.log(b) //{n: 1,x:{n:2}}

//证明箭头函数是定义时确定的this,以后都不能改变了
let fung
function fun(){
    if(fung){
        fung()
    }else{
        fung=()=>{
            console.log(this.x)
        }
        fung()
    }
}
fun.call({x:1}) //1
fun.call({x:2}) //1

// 尾递归优化
  function tco(f) {
    var value;
    var active = false;
    var accumulated = [];
  
    return function accumulator() {
      accumulated.push(arguments);
      if (!active) {  
        active = true;
        while (accumulated.length) {
          value = f.apply(this, accumulated.shift());
          //每次调用回调函数 都会调用sum，第一个被调用的sum函数会走循环，
          //然后剩下的sum执行时只会push参数，然后函数结束（调用栈中只会存在一个函数，优化效果达到）,
          //push进来的参数让第一次调用的sum中的循环继续
        }
        active = false;
        return value;
      }
    };
  }
  var sum = tco(function(x, y) {
    if (y > 0) {
      return sum(x + 1, y - 1)
    }
    else {
      return x
    }
  });
  sum(1, 10000000)

//蹦床函数进行尾递归优化
  function trampoline(f) {
    while (f && f instanceof Function) {
      f = f();
    }
    return f;
  }
  function sum(x, y) {
    if (y > 0) { 
    // 每次返回一个绑定了参数的函数 使蹦床函数可以继续执行，直到返回一个值，蹦床函数结束返回结果
      return sum.bind(null, x + 1, y - 1);
    } else {
      return x;
    }
  }
  trampoline(sum(1, 100000))
  


